﻿using System;
using System.Linq;
using System.Linq.Expressions;

namespace Tinter.Models
{
    /// <summary>
    /// Base interface for implement a "Repository Pattern", for
    /// more information about this pattern see http://martinfowler.com/eaaCatalog/repository.html
    /// or http://blogs.msdn.com/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx
    /// </summary>
    /// <remarks>
    /// Indeed, one might think that IDbSet already a generic repository and therefore
    /// would not need this item. Using this interface allows us to ensure PI principle
    /// within our domain model
    /// </remarks>
    /// <typeparam name="TEntity">Type of entity for this repository </typeparam>
    public interface IRepository<TEntity> where TEntity : EntityBase
    {
        /// <summary>
        /// Get the unit of work in this repository
        /// </summary>
        IDataContext DataContext { get; }

        /// <summary>
        /// Add item into repository
        /// </summary>
        /// <param name="item">Item to add to repository</param>
        void Add(TEntity item);

        /// <summary>
        /// Delete item 
        /// </summary>
        /// <param name="item">Item to delete</param>
        void Delete(TEntity item);

        /// <summary>
        ///Track entity into this repository, really in UnitOfWork. 
        ///In EF this can be done with Attach and with Update in NH
        /// </summary>
        /// <param name="item">Item to attach</param>
        void Track(TEntity item);

        /// <summary>
        /// Get element by entity key
        /// </summary>
        /// <param name="id">entity key value.</param>
        /// <returns></returns>
        TEntity Get(object id);

        /// <summary>
        /// Get all elements of type {TEntity} in repository
        /// </summary>
        /// <returns>List of selected elements</returns>
        IQueryable<TEntity> All();

        /// <summary>
        /// Get elements of type {TEntity} in repository
        /// </summary>
        /// <param name="filter">Filter that each element do match</param>
        /// <returns>List of selected elements</returns>
        IQueryable<TEntity> GetFiltered(Expression<Func<TEntity, bool>> filter);
    }
}
